Merge with latest xen-unstable
authordjm@kirby.fc.hp.com <djm@kirby.fc.hp.com>
Tue, 13 Sep 2005 16:14:16 +0000 (10:14 -0600)
committerdjm@kirby.fc.hp.com <djm@kirby.fc.hp.com>
Tue, 13 Sep 2005 16:14:16 +0000 (10:14 -0600)
1  2 
xen/arch/ia64/xen/xensetup.c

index a9eabb41be75d2178d4cfae87e3f28a5498dc733,0000000000000000000000000000000000000000..8b56f9817eb7e25a2d8d4ecaa3487bc6918ec88b
mode 100644,000000..100644
--- /dev/null
@@@ -1,401 -1,0 +1,402 @@@
- void arch_get_xen_caps(xen_capabilities_info_t *info)
 +/******************************************************************************
 + * xensetup.c
 + * Copyright (c) 2004-2005  Hewlett-Packard Co
 + *         Dan Magenheimer <dan.magenheimer@hp.com>
 + */
 +
 +#include <xen/config.h>
 +#include <xen/lib.h>
 +#include <xen/errno.h>
 +//#include <xen/spinlock.h>
 +#include <xen/multiboot.h>
 +#include <xen/sched.h>
 +#include <xen/mm.h>
 +#include <public/version.h>
 +//#include <xen/delay.h>
 +#include <xen/compile.h>
 +//#include <xen/console.h>
 +#include <xen/serial.h>
 +#include <xen/trace.h>
 +#include <asm/meminit.h>
 +#include <asm/page.h>
 +#include <asm/setup.h>
 +#include <xen/string.h>
 +
 +unsigned long xenheap_phys_end;
 +
 +char saved_command_line[COMMAND_LINE_SIZE];
 +
 +struct vcpu *idle_task[NR_CPUS] = { &idle0_vcpu };
 +
 +cpumask_t cpu_present_map;
 +
 +#ifdef CLONE_DOMAIN0
 +struct domain *clones[CLONE_DOMAIN0];
 +#endif
 +extern unsigned long domain0_ready;
 +
 +int find_max_pfn (unsigned long, unsigned long, void *);
 +void start_of_day(void);
 +
 +/* opt_nosmp: If true, secondary processors are ignored. */
 +static int opt_nosmp = 0;
 +boolean_param("nosmp", opt_nosmp);
 +
 +/* maxcpus: maximum number of CPUs to activate. */
 +static unsigned int max_cpus = NR_CPUS;
 +integer_param("maxcpus", max_cpus); 
 +
 +/*
 + * opt_xenheap_megabytes: Size of Xen heap in megabytes, including:
 + *    xen image
 + *    bootmap bits
 + *    xen heap
 + * Note: To allow xenheap size configurable, the prerequisite is
 + * to configure elilo allowing relocation defaultly. Then since
 + * elilo chooses 256M as alignment when relocating, alignment issue
 + * on IPF can be addressed.
 + */
 +unsigned int opt_xenheap_megabytes = XENHEAP_DEFAULT_MB;
 +unsigned long xenheap_size = XENHEAP_DEFAULT_SIZE;
 +extern long running_on_sim;
 +unsigned long xen_pstart;
 +
 +static int
 +xen_count_pages(u64 start, u64 end, void *arg)
 +{
 +    unsigned long *count = arg;
 +
 +    /* FIXME: do we need consider difference between DMA-usable memory and
 +     * normal memory? Seems that HV has no requirement to operate DMA which
 +     * is owned by Dom0? */
 +    *count += (end - start) >> PAGE_SHIFT;
 +    return 0;
 +}
 +
 +/* Find first hole after trunk for xen image */
 +static int
 +xen_find_first_hole(u64 start, u64 end, void *arg)
 +{
 +    unsigned long *first_hole = arg;
 +
 +    if ((*first_hole) == 0) {
 +      if ((start <= KERNEL_START) && (KERNEL_START < end))
 +          *first_hole = __pa(end);
 +    }
 +
 +    return 0;
 +}
 +
 +static void __init do_initcalls(void)
 +{
 +    initcall_t *call;
 +    for ( call = &__initcall_start; call < &__initcall_end; call++ )
 +        (*call)();
 +}
 +
 +/*
 + * IPF loader only supports one commaind line currently, for
 + * both xen and guest kernel. This function provides pre-parse
 + * to mixed command line, to split it into two parts.
 + *
 + * User should split the parameters by "--", with strings after
 + * spliter for guest kernel. Missing "--" means whole line belongs
 + * to guest. Example:
 + *    "com2=57600,8n1 console=com2 -- console=ttyS1 console=tty
 + * root=/dev/sda3 ro"
 + */
 +static char null[4] = { 0 };
 +
 +void early_cmdline_parse(char **cmdline_p)
 +{
 +    char *guest_cmd;
 +    char *split = "--";
 +
 +    if (*cmdline_p == NULL) {
 +      *cmdline_p = &null[0];
 +      saved_command_line[0] = '\0';
 +      return;
 +    }
 +
 +    guest_cmd = strstr(*cmdline_p, split);
 +    /* If no spliter, whole line is for guest */
 +    if (guest_cmd == NULL) {
 +      guest_cmd = *cmdline_p;
 +      *cmdline_p = &null[0];
 +    } else {
 +      *guest_cmd = '\0';      /* Split boot parameters for xen and guest */
 +      guest_cmd += strlen(split);
 +      while (*guest_cmd == ' ') guest_cmd++;
 +    }
 +
 +    strlcpy(saved_command_line, guest_cmd, COMMAND_LINE_SIZE);
 +    return;
 +}
 +
 +struct ns16550_defaults ns16550_com1 = {
 +    .baud      = BAUD_AUTO,
 +    .data_bits = 8,
 +    .parity    = 'n',
 +    .stop_bits = 1
 +};
 +
 +struct ns16550_defaults ns16550_com2 = {
 +    .baud      = BAUD_AUTO,
 +    .data_bits = 8,
 +    .parity    = 'n',
 +    .stop_bits = 1
 +};
 +
 +void start_kernel(void)
 +{
 +    unsigned char *cmdline;
 +    void *heap_start;
 +    int i;
 +    unsigned long max_mem, nr_pages, firsthole_start;
 +    unsigned long dom0_memory_start, dom0_memory_end;
 +    unsigned long initial_images_start, initial_images_end;
 +
 +    running_on_sim = is_platform_hp_ski();
 +    /* Kernel may be relocated by EFI loader */
 +    xen_pstart = ia64_tpa(KERNEL_START);
 +
 +    /* Must do this early -- e.g., spinlocks rely on get_current(). */
 +    //set_current(&idle0_vcpu);
 +    ia64_r13 = (void *)&idle0_vcpu;
 +    idle0_vcpu.domain = &idle0_domain;
 +
 +    early_setup_arch(&cmdline);
 +
 +    /* We initialise the serial devices very early so we can get debugging. */
 +    if (running_on_sim) hpsim_serial_init();
 +    else {
 +      ns16550_init(0, &ns16550_com1);
 +      /* Also init com2 for Tiger4. */
 +      ns16550_com2.io_base = 0x2f8;
 +      ns16550_com2.irq     = 3;
 +      ns16550_init(1, &ns16550_com2);
 +    }
 +    serial_init_preirq();
 +
 +    init_console();
 +    set_printk_prefix("(XEN) ");
 +
 +    /* xenheap should be in same TR-covered range with xen image */
 +    xenheap_phys_end = xen_pstart + xenheap_size;
 +    printk("xen image pstart: 0x%lx, xenheap pend: 0x%lx\n",
 +          xen_pstart, xenheap_phys_end);
 +
 +    /* Find next hole */
 +    firsthole_start = 0;
 +    efi_memmap_walk(xen_find_first_hole, &firsthole_start);
 +
 +    initial_images_start = xenheap_phys_end;
 +    initial_images_end = initial_images_start + ia64_boot_param->initrd_size;
 +
 +    /* Later may find another memory trunk, even away from xen image... */
 +    if (initial_images_end > firsthole_start) {
 +      printk("Not enough memory to stash the DOM0 kernel image.\n");
 +      printk("First hole:0x%lx, relocation end: 0x%lx\n",
 +              firsthole_start, initial_images_end);
 +      for ( ; ; );
 +    }
 +
 +    /* This copy is time consuming, but elilo may load Dom0 image
 +     * within xenheap range */
 +    printk("ready to move Dom0 to 0x%lx...", initial_images_start);
 +    memmove(__va(initial_images_start),
 +         __va(ia64_boot_param->initrd_start),
 +         ia64_boot_param->initrd_size);
 +    ia64_boot_param->initrd_start = initial_images_start;
 +    printk("Done\n");
 +
 +    /* first find highest page frame number */
 +    max_page = 0;
 +    efi_memmap_walk(find_max_pfn, &max_page);
 +    printf("find_memory: efi_memmap_walk returns max_page=%lx\n",max_page);
 +
 +    heap_start = memguard_init(ia64_imva(&_end));
 +    printf("Before heap_start: 0x%lx\n", heap_start);
 +    heap_start = __va(init_boot_allocator(__pa(heap_start)));
 +    printf("After heap_start: 0x%lx\n", heap_start);
 +
 +    reserve_memory();
 +
 +    efi_memmap_walk(filter_rsvd_memory, init_boot_pages);
 +    efi_memmap_walk(xen_count_pages, &nr_pages);
 +
 +    printk("System RAM: %luMB (%lukB)\n",
 +      nr_pages >> (20 - PAGE_SHIFT),
 +      nr_pages << (PAGE_SHIFT - 10));
 +
 +    init_frametable();
 +
 +    ia64_fph_enable();
 +    __ia64_init_fpu();
 +
 +    alloc_dom0();
 +#ifdef DOMU_BUILD_STAGING
 +    alloc_domU_staging();
 +#endif
 +
 +    end_boot_allocator();
 +
 +    init_xenheap_pages(__pa(heap_start), xenheap_phys_end);
 +    printk("Xen heap: %luMB (%lukB)\n",
 +      (xenheap_phys_end-__pa(heap_start)) >> 20,
 +      (xenheap_phys_end-__pa(heap_start)) >> 10);
 +
 +    late_setup_arch(&cmdline);
 +    setup_per_cpu_areas();
 +    mem_init();
 +
 +printk("About to call scheduler_init()\n");
 +    scheduler_init();
 +    local_irq_disable();
 +printk("About to call init_xen_time()\n");
 +    init_xen_time(); /* initialise the time */
 +printk("About to call ac_timer_init()\n");
 +    ac_timer_init();
 +// init_xen_time(); ???
 +
 +#ifdef CONFIG_SMP
 +    if ( opt_nosmp )
 +    {
 +        max_cpus = 0;
 +        smp_num_siblings = 1;
 +        //boot_cpu_data.x86_num_cores = 1;
 +    }
 +
 +    smp_prepare_cpus(max_cpus);
 +
 +    /* We aren't hotplug-capable yet. */
 +    //BUG_ON(!cpus_empty(cpu_present_map));
 +    for_each_cpu ( i )
 +        cpu_set(i, cpu_present_map);
 +
 +    //BUG_ON(!local_irq_is_enabled());
 +
 +printk("num_online_cpus=%d, max_cpus=%d\n",num_online_cpus(),max_cpus);
 +    for_each_present_cpu ( i )
 +    {
 +        if ( num_online_cpus() >= max_cpus )
 +            break;
 +        if ( !cpu_online(i) ) {
 +printk("About to call __cpu_up(%d)\n",i);
 +            __cpu_up(i);
 +      }
 +    }
 +
 +    printk("Brought up %ld CPUs\n", (long)num_online_cpus());
 +    smp_cpus_done(max_cpus);
 +#endif
 +
 +
 +      // FIXME: Should the following be swapped and moved later?
 +    schedulers_start();
 +    do_initcalls();
 +printk("About to call sort_main_extable()\n");
 +    sort_main_extable();
 +
 +    /* surrender usage of kernel registers to domain, use percpu area instead */
 +    __get_cpu_var(cpu_kr)._kr[IA64_KR_IO_BASE] = ia64_get_kr(IA64_KR_IO_BASE);
 +    __get_cpu_var(cpu_kr)._kr[IA64_KR_PER_CPU_DATA] = ia64_get_kr(IA64_KR_PER_CPU_DATA);
 +    __get_cpu_var(cpu_kr)._kr[IA64_KR_CURRENT_STACK] = ia64_get_kr(IA64_KR_CURRENT_STACK);
 +    __get_cpu_var(cpu_kr)._kr[IA64_KR_FPU_OWNER] = ia64_get_kr(IA64_KR_FPU_OWNER);
 +    __get_cpu_var(cpu_kr)._kr[IA64_KR_CURRENT] = ia64_get_kr(IA64_KR_CURRENT);
 +    __get_cpu_var(cpu_kr)._kr[IA64_KR_PT_BASE] = ia64_get_kr(IA64_KR_PT_BASE);
 +
 +    /* Create initial domain 0. */
 +printk("About to call do_createdomain()\n");
 +    dom0 = do_createdomain(0, 0);
 +    init_task.domain = &idle0_domain;
 +    init_task.processor = 0;
 +//    init_task.mm = &init_mm;
 +    init_task.domain->arch.mm = &init_mm;
 +//    init_task.thread = INIT_THREAD;
 +    //arch_do_createdomain(current);
 +#ifdef CLONE_DOMAIN0
 +    {
 +    int i;
 +    for (i = 0; i < CLONE_DOMAIN0; i++) {
 +      clones[i] = do_createdomain(i+1, 0);
 +        if ( clones[i] == NULL )
 +            panic("Error creating domain0 clone %d\n",i);
 +    }
 +    }
 +#endif
 +    if ( dom0 == NULL )
 +        panic("Error creating domain 0\n");
 +
 +    set_bit(_DOMF_privileged, &dom0->domain_flags);
 +
 +    /*
 +     * We're going to setup domain0 using the module(s) that we stashed safely
 +     * above our heap. The second module, if present, is an initrd ramdisk.
 +     */
 +printk("About to call construct_dom0()\n");
 +    dom0_memory_start = __va(ia64_boot_param->initrd_start);
 +    dom0_memory_end = ia64_boot_param->initrd_size;
 +    if ( construct_dom0(dom0, dom0_memory_start, dom0_memory_end,
 +                      0,
 +                        0,
 +                      0) != 0)
 +        panic("Could not set up DOM0 guest OS\n");
 +#ifdef CLONE_DOMAIN0
 +    {
 +    int i;
 +    dom0_memory_start = __va(ia64_boot_param->initrd_start);
 +    dom0_memory_end = ia64_boot_param->initrd_size;
 +    for (i = 0; i < CLONE_DOMAIN0; i++) {
 +printk("CONSTRUCTING DOMAIN0 CLONE #%d\n",i+1);
 +        if ( construct_domU(clones[i], dom0_memory_start, dom0_memory_end,
 +                        0, 
 +                        0,
 +                      0) != 0)
 +            panic("Could not set up DOM0 clone %d\n",i);
 +    }
 +    }
 +#endif
 +
 +    /* The stash space for the initial kernel image can now be freed up. */
 +    init_domheap_pages(ia64_boot_param->initrd_start,
 +                     ia64_boot_param->initrd_start + ia64_boot_param->initrd_size);
 +    if (!running_on_sim)  // slow on ski and pages are pre-initialized to zero
 +      scrub_heap_pages();
 +
 +printk("About to call init_trace_bufs()\n");
 +    init_trace_bufs();
 +
 +    /* Give up the VGA console if DOM0 is configured to grab it. */
 +#ifndef IA64
 +    console_endboot(cmdline && strstr(cmdline, "tty0"));
 +#endif
 +
 +#ifdef CLONE_DOMAIN0
 +    {
 +    int i;
 +    for (i = 0; i < CLONE_DOMAIN0; i++)
 +      domain_unpause_by_systemcontroller(clones[i]);
 +    }
 +#endif
 +    domain_unpause_by_systemcontroller(dom0);
 +    domain0_ready = 1;
 +    local_irq_enable();
 +printk("About to call startup_cpu_idle_loop()\n");
 +    startup_cpu_idle_loop();
 +}
 +
-     char *p=info->caps;
++void arch_get_xen_caps(xen_capabilities_info_t info)
 +{
-     BUG_ON((p-info->caps)>sizeof(*info));
++    char *p=info;
 +
 +    *p=0;
 +
 +    p+=sprintf(p,"xen_%d.%d_ia64 ",XEN_VERSION,XEN_SUBVERSION);
 +
-     if(p>info->caps) *(p-1) = 0;
++    *(p-1) = 0;
++
++    BUG_ON((p-info)>sizeof(xen_capabilities_info_t));
 +
 +}
 +